home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / gfx / x11 / twm_930531.lha / twm / icons.c < prev    next >
C/C++ Source or Header  |  1993-05-30  |  15KB  |  585 lines

  1. /*
  2.  * Copyright 1989 Massachusetts Institute of Technology
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and its
  5.  * documentation for any purpose and without fee is hereby granted, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of M.I.T. not be used in advertising
  9.  * or publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  M.I.T. makes no representations about the
  11.  * suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  15.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  16.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  17.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  18.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  19.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  20.  */
  21.  
  22. /**********************************************************************
  23.  *
  24.  * $XConsortium: icons.c,v 1.22 91/07/12 09:58:38 dave Exp $
  25.  *
  26.  * Icon releated routines
  27.  *
  28.  * 10-Apr-89 Tom LaStrange        Initial Version.
  29.  *
  30.  **********************************************************************/
  31.  
  32. #include <stdio.h>
  33. #include "twm.h"
  34. #include "screen.h"
  35. #include "icons.h"
  36. #include "gram.h"
  37. #include "parse.h"
  38. #include "util.h"
  39.  
  40. #define iconWidth(w)    (Scr->IconBorderWidth * 2 + w->icon_w_width)
  41. #define iconHeight(w)    (Scr->IconBorderWidth * 2 + w->icon_w_height)
  42.  
  43. static
  44. splitEntry (ie, grav1, grav2, w, h)
  45.     IconEntry    *ie;
  46.     int        grav1, grav2;
  47.     int        w, h;
  48. {
  49.     IconEntry    *new;
  50.  
  51.     switch (grav1) {
  52.     case D_NORTH:
  53.     case D_SOUTH:
  54.     if (w != ie->w)
  55.         splitEntry (ie, grav2, grav1, w, ie->h);
  56.     if (h != ie->h) {
  57.         new = (IconEntry *)malloc (sizeof (IconEntry));
  58.         new->twm_win = 0;
  59.         new->used = 0;
  60.         new->next = ie->next;
  61.         ie->next = new;
  62.         new->x = ie->x;
  63.         new->h = (ie->h - h);
  64.         new->w = ie->w;
  65.         ie->h = h;
  66.         if (grav1 == D_SOUTH) {
  67.         new->y = ie->y;
  68.         ie->y = new->y + new->h;
  69.         } else
  70.         new->y = ie->y + ie->h;
  71.     }
  72.     break;
  73.     case D_EAST:
  74.     case D_WEST:
  75.     if (h != ie->h)
  76.         splitEntry (ie, grav2, grav1, ie->w, h);
  77.     if (w != ie->w) {
  78.         new = (IconEntry *)malloc (sizeof (IconEntry));
  79.         new->twm_win = 0;
  80.         new->used = 0;
  81.         new->next = ie->next;
  82.         ie->next = new;
  83.         new->y = ie->y;
  84.         new->w = (ie->w - w);
  85.         new->h = ie->h;
  86.         ie->w = w;
  87.         if (grav1 == D_EAST) {
  88.         new->x = ie->x;
  89.         ie->x = new->x + new->w;
  90.         } else
  91.         new->x = ie->x + ie->w;
  92.     }
  93.     break;
  94.     }
  95. }
  96.  
  97. roundUp (v, multiple)
  98. {
  99.     return ((v + multiple - 1) / multiple) * multiple;
  100. }
  101.  
  102. PlaceIcon(tmp_win, def_x, def_y, final_x, final_y)
  103. TwmWindow *tmp_win;
  104. int def_x, def_y;
  105. int *final_x, *final_y;
  106. {
  107.     IconRegion    *ir;
  108.     IconEntry    *ie;
  109.     int        w = 0, h = 0;
  110.  
  111.     ie = 0;
  112.     for (ir = Scr->FirstRegion; ir; ir = ir->next) {
  113.     w = roundUp (iconWidth (tmp_win), ir->stepx);
  114.     h = roundUp (iconHeight (tmp_win), ir->stepy);
  115.     for (ie = ir->entries; ie; ie=ie->next) {
  116.         if (ie->used)
  117.         continue;
  118.         if (ie->w >= w && ie->h >= h)
  119.         break;
  120.     }
  121.     if (ie)
  122.         break;
  123.     }
  124.     if (ie) {
  125.     splitEntry (ie, ir->grav1, ir->grav2, w, h);
  126.     ie->used = 1;
  127.     ie->twm_win = tmp_win;
  128.     *final_x = ie->x + (ie->w - iconWidth (tmp_win)) / 2;
  129.     *final_y = ie->y + (ie->h - iconHeight (tmp_win)) / 2;
  130.     } else {
  131.     *final_x = def_x;
  132.     *final_y = def_y;
  133.     }
  134.     return;
  135. }
  136.  
  137. static IconEntry *
  138. FindIconEntry (tmp_win, irp)
  139.     TwmWindow   *tmp_win;
  140.     IconRegion    **irp;
  141. {
  142.     IconRegion    *ir;
  143.     IconEntry    *ie;
  144.  
  145.     for (ir = Scr->FirstRegion; ir; ir = ir->next) {
  146.     for (ie = ir->entries; ie; ie=ie->next)
  147.         if (ie->twm_win == tmp_win) {
  148.         if (irp)
  149.             *irp = ir;
  150.         return ie;
  151.         }
  152.     }
  153.     return 0;
  154. }
  155.  
  156. IconUp (tmp_win)
  157.     TwmWindow   *tmp_win;
  158. {
  159.     int        x, y;
  160.     int        defx, defy;
  161.     struct IconRegion *ir;
  162.  
  163.     /*
  164.      * If the client specified a particular location, let's use it (this might
  165.      * want to be an option at some point).  Otherwise, try to fit within the
  166.      * icon region.
  167.      */
  168.     if (tmp_win->wmhints && (tmp_win->wmhints->flags & IconPositionHint))
  169.       return;
  170.  
  171.     if (tmp_win->icon_moved) {
  172.     if (!XGetGeometry (dpy, tmp_win->icon_w, &JunkRoot, &defx, &defy,
  173.                &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth))
  174.       return;
  175.  
  176.     x = defx + ((int) JunkWidth) / 2;
  177.     y = defy + ((int) JunkHeight) / 2;
  178.  
  179.     for (ir = Scr->FirstRegion; ir; ir = ir->next) {
  180.         if (x >= ir->x && x < (ir->x + ir->w) &&
  181.         y >= ir->y && y < (ir->y + ir->h))
  182.           break;
  183.     }
  184.     if (!ir) return;        /* outside icon regions, leave alone */
  185.     }
  186.  
  187.     defx = -100;
  188.     defy = -100;
  189.     PlaceIcon(tmp_win, defx, defy, &x, &y);
  190.     if (x != defx || y != defy) {
  191.     XMoveWindow (dpy, tmp_win->icon_w, x, y);
  192.     tmp_win->icon_moved = FALSE;    /* since we've restored it */
  193.     }
  194. }
  195.  
  196. static IconEntry *
  197. prevIconEntry (ie, ir)
  198.     IconEntry    *ie;
  199.     IconRegion    *ir;
  200. {
  201.     IconEntry    *ip;
  202.  
  203.     if (ie == ir->entries)
  204.     return 0;
  205.     for (ip = ir->entries; ip->next != ie; ip=ip->next)
  206.     ;
  207.     return ip;
  208. }
  209.  
  210. /* old is being freed; and is adjacent to ie.  Merge
  211.  * regions together
  212.  */
  213.  
  214. static
  215. mergeEntries (old, ie)
  216.     IconEntry    *old, *ie;
  217. {
  218.     if (old->y == ie->y) {
  219.     ie->w = old->w + ie->w;
  220.     if (old->x < ie->x)
  221.         ie->x = old->x;
  222.     } else {
  223.     ie->h = old->h + ie->h;
  224.     if (old->y < ie->y)
  225.         ie->y = old->y;
  226.     }
  227. }
  228.  
  229. IconDown (tmp_win)
  230.     TwmWindow   *tmp_win;
  231. {
  232.     IconEntry    *ie, *ip, *in;
  233.     IconRegion    *ir;
  234.  
  235.     ie = FindIconEntry (tmp_win, &ir);
  236.     if (ie) {
  237.     ie->twm_win = 0;
  238.     ie->used = 0;
  239.     ip = prevIconEntry (ie, ir);
  240.     in = ie->next;
  241.     for (;;) {
  242.         if (ip && ip->used == 0 &&
  243.            ((ip->x == ie->x && ip->w == ie->w) ||
  244.             (ip->y == ie->y && ip->h == ie->h)))
  245.         {
  246.             ip->next = ie->next;
  247.             mergeEntries (ie, ip);
  248.             free ((char *) ie);
  249.         ie = ip;
  250.             ip = prevIconEntry (ip, ir);
  251.         } else if (in && in->used == 0 &&
  252.            ((in->x == ie->x && in->w == ie->w) ||
  253.             (in->y == ie->y && in->h == ie->h)))
  254.         {
  255.             ie->next = in->next;
  256.             mergeEntries (in, ie);
  257.             free ((char *) in);
  258.             in = ie->next;
  259.         } else
  260.         break;
  261.     }
  262.     }
  263. }
  264.  
  265. AddIconRegion(geom, grav1, grav2, stepx, stepy)
  266. char *geom;
  267. int grav1, grav2;
  268. {
  269.     IconRegion *ir;
  270.     int mask;
  271.  
  272.     ir = (IconRegion *)malloc(sizeof(IconRegion));
  273.     ir->next = NULL;
  274.     if (Scr->LastRegion)
  275.     Scr->LastRegion->next = ir;
  276.     Scr->LastRegion = ir;
  277.     if (!Scr->FirstRegion)
  278.     Scr->FirstRegion = ir;
  279.  
  280.     ir->entries = NULL;
  281.     ir->grav1 = grav1;
  282.     ir->grav2 = grav2;
  283.     if (stepx <= 0)
  284.     stepx = 1;
  285.     if (stepy <= 0)
  286.     stepy = 1;
  287.     ir->stepx = stepx;
  288.     ir->stepy = stepy;
  289.     ir->x = ir->y = ir->w = ir->h = 0;
  290.  
  291.     mask = XParseGeometry(geom, &ir->x, &ir->y, (unsigned int *)&ir->w, (unsigned int *)&ir->h);
  292.  
  293.     if (mask & XNegative)
  294.     ir->x += Scr->MyDisplayWidth - ir->w;
  295.  
  296.     if (mask & YNegative)
  297.     ir->y += Scr->MyDisplayHeight - ir->h;
  298.     ir->entries = (IconEntry *)malloc(sizeof(IconEntry));
  299.     ir->entries->next = 0;
  300.     ir->entries->x = ir->x;
  301.     ir->entries->y = ir->y;
  302.     ir->entries->w = ir->w;
  303.     ir->entries->h = ir->h;
  304.     ir->entries->twm_win = 0;
  305.     ir->entries->used = 0;
  306. }
  307.  
  308. #ifdef comment
  309. FreeIconEntries (ir)
  310.     IconRegion    *ir;
  311. {
  312.     IconEntry    *ie, *tmp;
  313.  
  314.     for (ie = ir->entries; ie; ie=tmp)
  315.     {
  316.     tmp = ie->next;
  317.     free ((char *) ie);
  318.     }
  319. }
  320. FreeIconRegions()
  321. {
  322.     IconRegion *ir, *tmp;
  323.  
  324.     for (ir = Scr->FirstRegion; ir != NULL;)
  325.     {
  326.     tmp = ir;
  327.     FreeIconEntries (ir);
  328.     ir = ir->next;
  329.     free((char *) tmp);
  330.     }
  331.     Scr->FirstRegion = NULL;
  332.     Scr->LastRegion = NULL;
  333. }
  334. #endif
  335.  
  336. CreateIconWindow(tmp_win, def_x, def_y)
  337. TwmWindow *tmp_win;
  338. int def_x, def_y;
  339. {
  340.     unsigned long event_mask;
  341.     unsigned long valuemask;        /* mask for create windows */
  342.     XSetWindowAttributes attributes;    /* attributes for create windows */
  343.     Pixmap pm = None;            /* tmp pixmap variable */
  344.     int final_x, final_y;
  345.     int x;
  346.  
  347.  
  348.     FB(tmp_win->iconc.fore, tmp_win->iconc.back);
  349.  
  350.     tmp_win->forced = FALSE;
  351.     tmp_win->icon_not_ours = FALSE;
  352.  
  353.     /* now go through the steps to get an icon window,  if ForceIcon is 
  354.      * set, then no matter what else is defined, the bitmap from the
  355.      * .twmrc file is used
  356.      */
  357.     if (Scr->ForceIcon)
  358.     {
  359.     char *icon_name;
  360.     Pixmap bm;
  361.  
  362.     icon_name = LookInNameList(Scr->IconNames, tmp_win->full_name);
  363.         if (icon_name == NULL)
  364.         icon_name = LookInList(Scr->IconNames, tmp_win->full_name,
  365.                    &tmp_win->class);
  366.  
  367.     bm = None;
  368.     if (icon_name != NULL)
  369.     {
  370.         if ((bm = (Pixmap)LookInNameList(Scr->Icons, icon_name)) == None)
  371.         {
  372.         if ((bm = GetBitmap (icon_name)) != None)
  373.             AddToList(&Scr->Icons, icon_name, (char *)bm);
  374.         }
  375.     }
  376.  
  377.     if (bm != None)
  378.     {
  379.         XGetGeometry(dpy, bm, &JunkRoot, &JunkX, &JunkY,
  380.         (unsigned int *) &tmp_win->icon_width, (unsigned int *)&tmp_win->icon_height,
  381.         &JunkBW, &JunkDepth);
  382.  
  383.         pm = XCreatePixmap(dpy, Scr->Root, tmp_win->icon_width,
  384.         tmp_win->icon_height, Scr->d_depth);
  385.  
  386.         /* the copy plane works on color ! */
  387.         XCopyPlane(dpy, bm, pm, Scr->NormalGC,
  388.         0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 );
  389.  
  390.         tmp_win->forced = TRUE;
  391.     }
  392.     }
  393.  
  394.     /* if the pixmap is still NULL, we didn't get one from the above code,
  395.      * that could mean that ForceIcon was not set, or that the window
  396.      * was not in the Icons list, now check the WM hints for an icon
  397.      */
  398.     if (pm == None && tmp_win->wmhints &&
  399.     tmp_win->wmhints->flags & IconPixmapHint)
  400.     {
  401.     
  402.     XGetGeometry(dpy,   tmp_win->wmhints->icon_pixmap,
  403.              &JunkRoot, &JunkX, &JunkY,
  404.          (unsigned int *)&tmp_win->icon_width, (unsigned int *)&tmp_win->icon_height, &JunkBW, &JunkDepth);
  405.  
  406.     pm = XCreatePixmap(dpy, Scr->Root,
  407.                tmp_win->icon_width, tmp_win->icon_height,
  408.                Scr->d_depth);
  409.  
  410.     XCopyPlane(dpy, tmp_win->wmhints->icon_pixmap, pm, Scr->NormalGC,
  411.         0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 );
  412.     }
  413.  
  414.     /* if we still haven't got an icon, let's look in the Icon list 
  415.      * if ForceIcon is not set
  416.      */
  417.     if (pm == None && !Scr->ForceIcon)
  418.     {
  419.     char *icon_name;
  420.     Pixmap bm;
  421.  
  422.     icon_name = LookInNameList(Scr->IconNames, tmp_win->full_name);
  423.         if (icon_name == NULL)
  424.         icon_name = LookInList(Scr->IconNames, tmp_win->full_name,
  425.                    &tmp_win->class);
  426.  
  427.     bm = None;
  428.     if (icon_name != NULL)
  429.     {
  430.         if ((bm = (Pixmap)LookInNameList(Scr->Icons, icon_name)) == None)
  431.         {
  432.         if ((bm = GetBitmap (icon_name)) != None)
  433.             AddToList(&Scr->Icons, icon_name, (char *)bm);
  434.         }
  435.     }
  436.  
  437.     if (bm != None)
  438.     {
  439.         XGetGeometry(dpy, bm, &JunkRoot, &JunkX, &JunkY,
  440.         (unsigned int *)&tmp_win->icon_width, (unsigned int *)&tmp_win->icon_height,
  441.         &JunkBW, &JunkDepth);
  442.  
  443.         pm = XCreatePixmap(dpy, Scr->Root, tmp_win->icon_width,
  444.         tmp_win->icon_height, Scr->d_depth);
  445.  
  446.         /* the copy plane works on color ! */
  447.         XCopyPlane(dpy, bm, pm, Scr->NormalGC,
  448.         0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 );
  449.     }
  450.     }
  451.  
  452.     /* if we still don't have an icon, assign the UnknownIcon */
  453.  
  454.     if (pm == None && Scr->UnknownPm != None)
  455.     {
  456.     tmp_win->icon_width = Scr->UnknownWidth;
  457.     tmp_win->icon_height = Scr->UnknownHeight;
  458.  
  459.     pm = XCreatePixmap(dpy, Scr->Root, tmp_win->icon_width,
  460.         tmp_win->icon_height, Scr->d_depth);
  461.  
  462.     /* the copy plane works on color ! */
  463.     XCopyPlane(dpy, Scr->UnknownPm, pm, Scr->NormalGC,
  464.         0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 );
  465.     }
  466.  
  467.     if (pm == None)
  468.     {
  469.     tmp_win->icon_height = 0;
  470.     tmp_win->icon_width = 0;
  471.     valuemask = 0;
  472.     }
  473.     else
  474.     {
  475.     valuemask = CWBackPixmap;
  476.     attributes.background_pixmap = pm;
  477.     }
  478.  
  479.     tmp_win->icon_w_width = XTextWidth(Scr->IconFont.font,
  480.     tmp_win->icon_name, strlen(tmp_win->icon_name));
  481.  
  482.     tmp_win->icon_w_width += 6;
  483.     if (tmp_win->icon_w_width < tmp_win->icon_width)
  484.     {
  485.     tmp_win->icon_x = (tmp_win->icon_width - tmp_win->icon_w_width)/2;
  486.     tmp_win->icon_x += 3;
  487.     tmp_win->icon_w_width = tmp_win->icon_width;
  488.     }
  489.     else
  490.     {
  491.     tmp_win->icon_x = 3;
  492.     }
  493.     tmp_win->icon_y = tmp_win->icon_height + Scr->IconFont.height;
  494.     tmp_win->icon_w_height = tmp_win->icon_height + Scr->IconFont.height + 4;
  495.  
  496.     event_mask = 0;
  497.     if (tmp_win->wmhints && tmp_win->wmhints->flags & IconWindowHint)
  498.     {
  499.     tmp_win->icon_w = tmp_win->wmhints->icon_window;
  500.     if (tmp_win->forced ||
  501.         XGetGeometry(dpy, tmp_win->icon_w, &JunkRoot, &JunkX, &JunkY,
  502.              (unsigned int *)&tmp_win->icon_w_width, (unsigned int *)&tmp_win->icon_w_height,
  503.              &JunkBW, &JunkDepth) == 0)
  504.     {
  505.         tmp_win->icon_w = None;
  506.         tmp_win->wmhints->flags &= ~IconWindowHint;
  507.     }
  508.     else
  509.     {
  510.         tmp_win->icon_not_ours = TRUE;
  511.         event_mask = EnterWindowMask | LeaveWindowMask;
  512.     }
  513.     }
  514.     else
  515.     {
  516.     tmp_win->icon_w = None;
  517.     }
  518.  
  519.     if (tmp_win->icon_w == None)
  520.     {
  521.     tmp_win->icon_w = XCreateSimpleWindow(dpy, Scr->Root,
  522.         0,0,
  523.         tmp_win->icon_w_width, tmp_win->icon_w_height,
  524.         Scr->IconBorderWidth, tmp_win->icon_border, tmp_win->iconc.back);
  525.     event_mask = ExposureMask;
  526.     }
  527.  
  528.     XSelectInput (dpy, tmp_win->icon_w,
  529.           KeyPressMask | ButtonPressMask | ButtonReleaseMask |
  530.           event_mask);
  531.  
  532.     tmp_win->icon_bm_w = None;
  533.     if (pm != None &&
  534.     (! (tmp_win->wmhints && tmp_win->wmhints->flags & IconWindowHint)))
  535.     {
  536.     int y;
  537.  
  538.     y = 0;
  539.     if (tmp_win->icon_w_width == tmp_win->icon_width)
  540.         x = 0;
  541.     else
  542.         x = (tmp_win->icon_w_width - tmp_win->icon_width)/2;
  543.  
  544.     tmp_win->icon_bm_w = XCreateWindow (dpy, tmp_win->icon_w, x, y,
  545.                         (unsigned int)tmp_win->icon_width,
  546.                         (unsigned int)tmp_win->icon_height,
  547.                         (unsigned int) 0, Scr->d_depth,
  548.                         (unsigned int) CopyFromParent,
  549.                         Scr->d_visual, valuemask,
  550.                         &attributes);
  551.     }
  552.  
  553.     /* I need to figure out where to put the icon window now, because 
  554.      * getting here means that I am going to make the icon visible
  555.      */
  556.     if (tmp_win->wmhints &&
  557.     tmp_win->wmhints->flags & IconPositionHint)
  558.     {
  559.     final_x = tmp_win->wmhints->icon_x;
  560.     final_y = tmp_win->wmhints->icon_y;
  561.     }
  562.     else
  563.     {
  564.     PlaceIcon(tmp_win, def_x, def_y, &final_x, &final_y);
  565.     }
  566.  
  567.     if (final_x > Scr->MyDisplayWidth)
  568.     final_x = Scr->MyDisplayWidth - tmp_win->icon_w_width -
  569.         (2 * Scr->IconBorderWidth);
  570.  
  571.     if (final_y > Scr->MyDisplayHeight)
  572.     final_y = Scr->MyDisplayHeight - tmp_win->icon_height -
  573.         Scr->IconFont.height - 4 - (2 * Scr->IconBorderWidth);
  574.  
  575.     XMoveWindow(dpy, tmp_win->icon_w, final_x, final_y);
  576.     tmp_win->iconified = TRUE;
  577.  
  578.     XMapSubwindows(dpy, tmp_win->icon_w);
  579.     XSaveContext(dpy, tmp_win->icon_w, TwmContext, (caddr_t)tmp_win);
  580.     XSaveContext(dpy, tmp_win->icon_w, ScreenContext, (caddr_t)Scr);
  581.     XDefineCursor(dpy, tmp_win->icon_w, Scr->IconCursor);
  582.     if (pm) XFreePixmap (dpy, pm);
  583.     return;
  584. }
  585.